package de.piratech.dasding.services.impl;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.grum.geocalc.Coordinate;
import com.grum.geocalc.DegreeCoordinate;
import com.grum.geocalc.EarthCalc;
import com.grum.geocalc.Point;

import de.piratech.dasding.data.AbstractAction;
import de.piratech.dasding.data.Location;
import de.piratech.dasding.data.database.DatabaseException;
import de.piratech.dasding.services.LocationFilter;

@Service
public class GeoCalc implements LocationFilter {

  private static final Logger LOG = LoggerFactory.getLogger(GeoCalc.class);

  @Override
  public <K extends AbstractAction> List<K> getEventsInArea(List<K> events,
      Location startPoint, float distance) throws DatabaseException {
    Point center = getPoint(startPoint);
    return getEventsInArea(events, center, distance);
  }

  @Override
  public <K extends AbstractAction> List<K> getEventsInArea(List<K> actions,
      double latitude, double longitude, float maxDistance)
      throws DatabaseException {
    Point startPoint = getPoint(latitude, longitude);
    return getEventsInArea(actions, startPoint, maxDistance);
  }

  private <K extends AbstractAction> List<K> getEventsInArea(List<K> events,
      Point startPoint, float maxDistance) {
    // api needs distance in meters
    maxDistance = maxDistance * 1000;

    List<K> matching = new ArrayList<K>();
    for (K event : events) {
      Point point = getPoint(event.getLocation());
      double distance = EarthCalc.getDistance(startPoint, point);
      if (distance < maxDistance) {
        matching.add(event);
      }
    }
    return matching;
  }

  private Point getPoint(Location location) {
    Coordinate lat = new DegreeCoordinate(location.getLatitude());
    Coordinate lng = new DegreeCoordinate(location.getLongitude());
    Point point = new Point(lat, lng);
    return point;
  }

  private Point getPoint(double latitude, double longitude) {
    Coordinate lat = new DegreeCoordinate(latitude);
    Coordinate lng = new DegreeCoordinate(longitude);
    Point point = new Point(lat, lng);
    return point;
  }

}
